/**
******************************************************************************
* @file    stm32_eval_spi_sd.h
* @author  MCD Application Team
* @version V4.5.1
* @date    20-September-2021
* @brief   This file contains all the functions prototypes for the stm32_eval_spi_sd
*          firmware driver.
******************************************************************************
* @attention
*
* Copyright (c) 2011 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32_EVAL_SPI_SD_H
#define __STM32_EVAL_SPI_SD_H

#ifdef __cplusplus
extern "C" {
#endif


typedef enum
{
    /**
    * @brief  SD reponses and error flags
    */
    SD_RESPONSE_NO_ERROR            = 0x00,
    SD_IN_IDLE_STATE                = 0x01,
    SD_ERASE_RESET                  = 0x02,
    SD_ILLEGAL_COMMAND              = 0x04,
    SD_COM_CRC_ERROR                = 0x08,
    SD_ERASE_SEQUENCE_ERROR         = 0x10,
    SD_ADDRESS_ERROR                = 0x20,
    SD_PARAMETER_ERROR              = 0x40,
    SD_RESPONSE_FAILURE             = 0xFF,

    /**
    * @brief  Data response error
    */
    SD_DATA_OK                      = 0x05,
    SD_DATA_CRC_ERROR               = 0x0B,
    SD_DATA_WRITE_ERROR             = 0x0D,
    SD_DATA_OTHER_ERROR             = 0xFF,
} SD_Error;

/** 
* @brief  Card Specific Data: CSD2.0 Register
*/ 
typedef struct
{
    uint32_t CSDStruct              : 2;            /*!< CSD structure */
    uint32_t Reserved1              : 6;            /*!< Reserved */
    uint32_t TAAC                   : 8;            /*!< Data read access-time 1 */
    uint32_t NSAC                   : 8;            /*!< Data read access-time 2 in CLK cycles */
    uint32_t MaxBusClkFrec          : 8;            /*!< Max. bus clock frequency */
    uint32_t CardComdClasses        : 12;           /*!< Card command classes */
    uint32_t RdBlockLen             : 4;            /*!< Max. read data block length */
    uint32_t PartBlockRead          : 1;            /*!< Partial blocks for read allowed */
    uint32_t WrBlockMisalign        : 1;            /*!< Write block misalignment */
    uint32_t RdBlockMisalign        : 1;            /*!< Read block misalignment */
    uint32_t DSRImpl                : 1;            /*!< DSR implemented */
    uint32_t Reserved2              : 6;            /*!< Reserved */
    uint32_t DeviceSize             : 22;           /*!< Device Size */
    uint32_t DeviceSizeMul          : 1;            /*!< Device size multiplier */
    uint32_t EraseSingEnable        : 1;            /*!< Erase group size */
    uint32_t EraseGrSize            : 7;            /*!< Erase group size */
    uint32_t WrProtectGrSize        : 7;            /*!< Write protect group size */
    uint32_t WrProtectGrEnable      : 1;            /*!< Write protect group enable */
    uint32_t ManDeflECC             : 2;            /*!< Content protection application */
    uint32_t WrSpeedFact            : 3;            /*!< Write speed factor */
    uint32_t MaxWrBlockLen          : 4;            /*!< Max. write data block length */
    uint32_t WriteBlockPaPartial    : 1;            /*!< Partial blocks for write allowed */
    uint32_t ContentProtectAppli    : 5;            /*!< Content protection application */
    uint32_t FileFormatGrouop       : 1;            /*!< File format group */
    uint32_t CopyFlag               : 1;            /*!< Copy flag (OTP) */
    uint32_t PermWrProtect          : 1;            /*!< Permanent write protection */
    uint32_t TempWrProtect          : 1;            /*!< Temporary write protection */
    uint32_t FileFormat             : 2;            /*!< File Format */
    uint32_t ECC                    : 2;            /*!< ECC code*/
    uint32_t CSD_CRC                : 7;            /*!< CSD CRC */
    uint32_t Reserved6              : 1;            /*!< always 1 */
} SD_CSD;

/** 
* @brief  Card Identification Data: CID Register
*/
typedef struct
{
    uint32_t ManufacturerID         : 8;            /*!< ManufacturerID */
    uint32_t OEM_AppliID            : 16;           /*!< OEM/Application ID */
    uint32_t ProdNameH              : 32;           /*!< Product Name part1 */
    uint32_t ProdNameL              : 8;            /*!< Product Name part2*/
    uint32_t ProdRev                : 8;            /*!< Product Revision */
    uint32_t ProdSN                 : 32;           /*!< Product Serial Number */
    uint32_t Reserved1              : 4;            /*!< Reserved1 */
    uint32_t ManufactDate           : 12;           /*!< Manufacturing Date */
    uint32_t CID_CRC                : 7;            /*!< CID CRC */
    uint32_t Reserved2              : 1;            /*!< always 1 */
} SD_CID;

/** 
* @brief SD Card information
*/
typedef struct
{
    SD_CSD SD_csd;
    SD_CID SD_cid;
    uint32_t CardCapacity;                          /*!< Card Capacity（KB） */
    uint16_t CardBlockSize;                         /*!< Card Block Size（Byte） */
} SD_CardInfo;

/**
* @brief  Start Data tokens:
*         Tokens (necessary because at nop/idle (and CS active) only 0xff is 
*         on the data/command line)  
*/
#define SD_START_DATA_SINGLE_BLOCK_READ     0xFE    /*!< Data token start byte, Start Single Block Read */
#define SD_START_DATA_MULTIPLE_BLOCK_READ   0xFE    /*!< Data token start byte, Start Multiple Block Read */
#define SD_START_DATA_SINGLE_BLOCK_WRITE    0xFE    /*!< Data token start byte, Start Single Block Write */
#define SD_START_DATA_MULTIPLE_BLOCK_WRITE  0xFD    /*!< Data token start byte, Start Multiple Block Write */
#define SD_STOP_DATA_MULTIPLE_BLOCK_WRITE   0xFD    /*!< Data toke stop byte, Stop Multiple Block Write */

/**
* @brief  Commands: CMDxx = CMD-number | 0x40
*/
#define SD_CMD_GO_IDLE_STATE                0       /*!< CMD0  = 0x40 */
#define SD_CMD_SEND_OP_COND                 1       /*!< CMD1  = 0x41 */
#define SD_CMD_ALL_SEND_CID                 2       /*!< CMD2  = 0x42, ALL_SEND_CID */
#define SD_CMD_SEND_RELATIVE_ADDR           3       /*!< CMD3  = 0x43, SEND_RELATIVE_ADDR */
#define SD_CMD_SET_DSR                      4       /*!< CMD4  = 0x44, SET_DSR */
#define SD_CMD_SWITCH_FUNC                  6       /*!< CMD6  = 0x46, SWITCH_FUNC */
#define SD_CMD_SELECT_DESELECT_CARD         7       /*!< CMD7  = 0x47, SELECT_DESELECT_CARD */
#define SD_CMD_SEND_IF_COND                 8       /*!< CMD8  = 0x48, SEND_IF_COND */
#define SD_CMD_SEND_CSD                     9       /*!< CMD9  = 0x49 */
#define SD_CMD_SEND_CID                     10      /*!< CMD10 = 0x4A */
#define SD_CMD_STOP_TRANSMISSION            12      /*!< CMD12 = 0x4C */
#define SD_CMD_SEND_STATUS                  13      /*!< CMD13 = 0x4D */
#define SD_CMD_GO_INACTIVE_STATE            15      /*!< CMD15 = 0x4F, GO_INACTIVE_STATE */
#define SD_CMD_SET_BLOCKLEN                 16      /*!< CMD16 = 0x50 */
#define SD_CMD_READ_SINGLE_BLOCK            17      /*!< CMD17 = 0x51 */
#define SD_CMD_READ_MULT_BLOCK              18      /*!< CMD18 = 0x52 */
#define SD_CMD_SET_BLOCK_COUNT              23      /*!< CMD23 = 0x57 */
#define SD_CMD_WRITE_SINGLE_BLOCK           24      /*!< CMD24 = 0x58 */
#define SD_CMD_WRITE_MULT_BLOCK             25      /*!< CMD25 = 0x59 */
#define SD_CMD_PROG_CSD                     27      /*!< CMD27 = 0x5B */
#define SD_CMD_SET_WRITE_PROT               28      /*!< CMD28 = 0x5C */
#define SD_CMD_CLR_WRITE_PROT               29      /*!< CMD29 = 0x5D */
#define SD_CMD_SEND_WRITE_PROT              30      /*!< CMD30 = 0x5E */
#define SD_CMD_SD_ERASE_GRP_START           32      /*!< CMD32 = 0x60 */
#define SD_CMD_SD_ERASE_GRP_END             33      /*!< CMD33 = 0x61 */
#define SD_CMD_UNTAG_SECTOR                 34      /*!< CMD34 = 0x62 */
#define SD_CMD_ERASE_GRP_START              35      /*!< CMD35 = 0x63 */
#define SD_CMD_ERASE_GRP_END                36      /*!< CMD36 = 0x64 */
#define SD_CMD_UNTAG_ERASE_GROUP            37      /*!< CMD37 = 0x65 */
#define SD_CMD_ERASE                        38      /*!< CMD38 = 0x66 */
#define SD_CMD_LOCK_UNLOCK                  42      /*!< CMD42 = 0x6A, LOCK_UNLOCK */
#define SD_CMD_APP_CMD                      55      /*!< CMD55 = 0x77, APP_CMD */
#define SD_CMD_GEN_CMD                      56      /*!< CMD56 = 0x78, GEN_CMD */

/* SD memory card application specific commands index */
#define SD_APPCMD_SET_BUS_WIDTH             6       /* ACMD6, SET_BUS_WIDTH */
#define SD_APPCMD_SD_STATUS                 13      /* ACMD13, SD_STATUS */
#define SD_APPCMD_SEND_NUM_WR_BLOCKS        22      /* ACMD22, SEND_NUM_WR_BLOCKS */
#define SD_APPCMD_SET_WR_BLK_ERASE_COUNT    23      /* ACMD23, SET_WR_BLK_ERASE_COUNT */
#define SD_APPCMD_SD_SEND_OP_COND           41      /* ACMD41, SD_SEND_OP_COND */
#define SD_APPCMD_SET_CLR_CARD_DETECT       42      /* ACMD42, SET_CLR_CARD_DETECT */
#define SD_APPCMD_SEND_SCR                  51      /* ACMD51, SEND_SCR */


SD_Error SD_Init(void);
SD_Error SD_GetCardInfo(SD_CardInfo *cardinfo);
SD_Error SD_GetCSDRegister(SD_CSD* SD_csd);
SD_Error SD_GetCIDRegister(SD_CID* SD_cid);

SD_Error SD_ReadBlock(void* pvDatas, uint32_t uiBlockAddr, int32_t iBlockSize);
SD_Error SD_ReadMultiBlocks(void* pvDatas, uint32_t uiBlockAddr, int32_t iBlockSize, int32_t iBlockNumber);
SD_Error SD_WriteBlock(void* pvDatas, uint32_t uiBlockAddr, int32_t iBlockSize);
SD_Error SD_WriteMultiBlocks(const void* pvDatas, uint32_t uiBlockAddr, int32_t iBlockSize, int32_t iBlockNumber);

SD_Error SD_TypeInit(void);
SD_Error SD_GoIdleState(void);


#ifdef __cplusplus
}
#endif

#endif /* __STM32_EVAL_SPI_SD_H */
